package com.ruoyi.web.controller.iot.utils.jar;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;

public class Demo {

	public static String jarFilePath = "G:\\code\\ProjectJava\\lamp_Iot\\iot-lampv1\\target\\iot-lampv1-sdk-1.0.0-SNAPSHOT.jar";

	public static void main(String[] args) throws MalformedURLException {
		File file = new File(jarFilePath);

		if (!file.exists()) {
			System.out.println("文件不存在！");
			return;
		}
		if (!file.isFile()) {
			System.out.println("读取的为文件夹而非文件！");
			return;
		}
		if (!file.canRead()) {
			System.out.println("当前文件不可读！");
			return;
		}
		URL url1 = file.toURI().toURL();
		URLClassLoader jarUrlClassLoader = new URLClassLoader(new URL[] { url1 },
				Thread.currentThread().getContextClassLoader());
		JarFile jarFile = null;
		try {
			jarFile = new JarFile(file);
			// 获取jar中实际的MAINFEST.MF文件
			Manifest manifest = jarFile.getManifest();
			pringManifestFile(manifest);
			// 开始获取jar中的.class文件
			Enumeration<JarEntry> entries = jarFile.entries();
			List<String> classNames = getClassNames(entries);
			classNames.forEach(x -> {
				if (x.endsWith("Request")) {
					loadAndInstanceClass(x, jarUrlClassLoader);
				}
			});

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (jarFile != null) {
				try {
					jarFile.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 加载类和实例化类
	 * @param clazzName
	 * @param classLoader
	 */
	private static void loadAndInstanceClass(String clazzName, ClassLoader classLoader) {
		try {
			// 需要使用其他的classLoader加载
			Class<?> forName = classLoader.loadClass(clazzName);
			System.out.println(forName.getName());
			try {
				Object newInstance = forName.newInstance();
				System.out.println(newInstance.hashCode());
			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * 打印并获取所有的class
	 * @param entries
	 * @return
	 */
	private static List<String> getClassNames(Enumeration<JarEntry> entries) {
		List<String> classNames = new ArrayList<String>();
		while (entries.hasMoreElements()) {
			JarEntry nextElement = entries.nextElement();
			String name = nextElement.getName();
			// 这个获取的就是一个实体类class java.util.jar.JarFile$JarFileEntry
			// Class<? extends JarEntry> class1 = nextElement.getClass();
			System.out.println("entry name=" + name);
			// 这样就获取所有的jar中的class文件

			// 加载某个class文件，并实现动态运行某个class
			if (name.endsWith(".class")) {
				String replace = name.replace(".class", "").replace("/", ".");
				System.out.println(replace);
				classNames.add(replace);
			}
		}
		return classNames;
	}

	/**
	 * 输出当前的manifest文件中的信息内容
	 * @param manifest
	 */
	private static void pringManifestFile(Manifest manifest) {
		Attributes mainAttributes = manifest.getMainAttributes();
		Set<Map.Entry<Object, Object>> entrySet = mainAttributes.entrySet();
		Iterator<Map.Entry<Object, Object>> iterator = entrySet.iterator();
		// 打印并显示当前的MAINFEST.MF文件中的信息
		while (iterator.hasNext()) {
			Map.Entry<Object, Object> next = iterator.next();
			Object key = next.getKey();
			Object value = next.getValue();
			// 这里可以获取到Class-Path,或者某个执行的Main-Class
			System.out.println(key + ": " + value);
		}
	}
}

